home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9310.ZIP
/
1993-OCT.ZIP
/
LINKLIST.ASC
< prev
next >
Wrap
Text File
|
1993-09-21
|
33KB
|
1,227 lines
_COMPARING OBJECT-ORIENTED LANGUAGES_
by Michael Floyd
[LISTING ONE]
C++ Implementation by David Betz (Dr. Dobb's Journal)
#include <iostream.h>
/* any object that will appear in a list must inherit from this class */
class MyListData {
public:
virtual void Print(void);
};
void MyListData::Print(void)
{
cout << "No print method!\n";
}
class MyListElement {
MyListData *data;
MyListElement *next;
public:
MyListElement(MyListData *initialData) { data = initialData; next = nil; }
friend class MyList;
};
class MyList : public MyListData {
MyListElement *head;
MyListElement *tail;
public:
MyList(void) { head = tail = nil; }
void AddToList(MyListData *data);
void Print(void);
};
void MyList::AddToList(MyListData *data)
{
MyListElement *newElement = new MyListElement(data);
if (head == nil)
head = tail = newElement;
else {
tail->next = newElement;
tail = newElement;
}
}
void MyList::Print(void)
{
MyListElement *element;
for (element = head; element != nil; element = element->next)
element->data->Print();
}
class MyNumber : public MyListData {
int value;
public:
MyNumber(int initialValue) { value = initialValue; }
virtual void Print(void);
};
void MyNumber::Print(void)
{
cout << "Number: " << value << "\n";
}
class MyPoint : public MyListData {
int x;
int y;
public:
MyPoint(int initialX,int initialY) { x = initialX; y = initialY; }
virtual void Print(void);
};
void MyPoint::Print(void)
{
cout << "Point: " << x << "," << y << "\n";
}
void main(void)
{
MyList *list1 = new MyList;
MyList *list2 = new MyList;
MyNumber *n1 = new MyNumber(10);
MyNumber *n2 = new MyNumber(20);
MyPoint *p1 = new MyPoint(2,3);
MyPoint *p2 = new MyPoint(4,5);
/* build the lists */
list1->AddToList(n1);
list1->AddToList(n2);
list1->AddToList(p1);
list2->AddToList(n2); /* an object can be in more than one list */
list2->AddToList(p1); /* at the same time */
list2->AddToList(p2);
list2->AddToList(list1); /* we can even put a list into another list */
/* print the lists */
cout << "list1:\n";
list1->Print();
cout << "list2:\n";
list2->Print();
}
[LISTING TWO]
Objective-C Implementation by Stephen Asbury (Next Computer)
#import <stdio.h>
#import <objc/Object.h>/* Include the header for the Root class */
@interface LinkedListNode:Object /* declare a node class */
{
id value;/* a node can store an object of any class as it's
value */
id next;
}
- setValue:newValue;
- value;
- setNext:newNext;
- next;
- print;
@end
@implementation LinkedListNode /* implement the node class */
- setValue:newValue {value = newValue; return self;}
- value {return value;}
- setNext:newNext {next = newNext; return self;}
- next {return next;}
- print
{ /* In order to allow any object to be added to the list, we first check
* to see if the value can print, if so have it print */
if([value respondsTo:@selector(print)] == YES) [value print];
return self;
}
@end
@interface LinkedList:Object /* declare a linked list class */
{id tail,head;}
- addObjectToList:theObject;
- print;
@end
@implementation LinkedList /* implement the linked list class */
- init /* refine the init method of the super class */
{
self = [super init];
tail = head = nil;
return self;
}
- addNodeToList:newNode /* private method used only by the object */
{
if(head == nil)
head = tail = newNode;
else{
[tail setNext:newNode];
tail = newNode;
}
return self;
}
- addObjectToList:theObject
{
id newNode = [[[LinkedListNode alloc] init]
setValue:theObject];
[self addNodeToList:newNode];
return self;
}
- print
{
id element;
for(element = head;element != nil;element = [element next])
[element print];
return self;
}
@end
@interface MyNumber:Object /* declare a number class */
{float value;}
- initValue:(float)aValue;
- print;
@end
@implementation MyNumber /* implement the number class */
- initValue:(float)aValue
{
self = [super init];
value = aValue;
return self;
}
- print {printf("Number %f\n",value); return self;}
@end
@interface Point:Object /* declare a point class */
{float X,Y;}
- initX:(float)anX y:(float)anY;
- print;
@end
@implementation Point /* implement the point class */
- initX:(float)anX y:(float)anY
{
self = [super init];
X = anX;
Y = anY;
return self;
}
- print { printf("Point %f , %f\n",X,Y); return self; }
@end
void main(void)
{
id list1 = [[LinkedList alloc] init];
id list2 = [[LinkedList alloc] init];
id number1 = [[MyNumber alloc] initValue:10];
id number2 = [[MyNumber alloc] initValue:20];
id point1 = [[Point alloc] initX:2 y:3];
id point2 = [[Point alloc] initX:4 y:5];
/* Build the Lists */
[list1 addObjectToList:number1];
[list1 addObjectToList:number2];
[list1 addObjectToList:point1];
[list2 addObjectToList:number2];/* an object can be in
multiple list */
[list2 addObjectToList:point1];
[list2 addObjectToList:point2];
[list2 addObjectToList:list1];/* lists can contatin lists */
printf("List 1\n");
[list1 print];
printf("List 2\n");
[list2 print];
exit(0);
}
[LISTING THREE]
Turbo Pascal Implementation by Michael Floyd (Dr. Dobb's Journal)
Program LListObj;
Type
PMyListData = ^MyListData;
MyListData = object
procedure Print; virtual;
end;
PMyListElement = ^MyListElement;
MyListElement = object
Data : PMyListData;
Next : PMyListElement;
constructor Init(initialData: PMyListData);
end;
PMyList = ^MyList;
MyList = object(MyListData)
Head, Tail: PMyListElement;
constructor Init;
procedure AddToList(var Data: PMyListData);
procedure Print; virtual;
end;
PMyNumber = ^MyNumber;
MyNumber = object(MyListData)
Value : Integer;
constructor Init(initialValue: Integer);
procedure Print; virtual;
end;
PMyPoint = ^MyPoint;
MyPoint = object(MyListData)
X, Y: Integer;
constructor Init(initialX, initialY: Integer);
procedure Print; virtual;
end;
{ MyListElement Methods }
constructor MyListElement.Init(initialData: PMyListData);
begin
data := initialData;
next := nil;
end;
{ MyListData Methods }
procedure MyListData.Print;
begin
writeln('No Print Method!');
end;
{ MyList Methods }
constructor MyList.Init;
begin
Head:= nil;
Tail:= nil;
end;
procedure MyList.AddToList(var Data: PMyListData);
var
Added : PMyListElement;
begin
Added := New(PMyListElement,Init(Data));
If Head = nil then
begin
Head := Added;
Tail := Added;
end
Else begin
Tail^.Next := Added;
Tail := Added;
end;
Added^.Next := nil;
end;
procedure MyList.Print;
var
Current : PMyListElement;
begin
Current := Head;
while Current <> nil do
begin
Current^.Data^.Print;
Current := Current^.Next;
end;
end;
{ MyNumber Methods }
constructor MyNumber.Init(initialValue: Integer);
begin
Value := initialValue;
end;
procedure MyNumber.Print;
begin
writeln('Number: ', Value);
end;
{ MyPoint Methods }
constructor MyPoint.Init(initialX, initialY: Integer);
begin
X := initialX;
Y := initialY;
end;
procedure MyPoint.Print;
begin
writeln('Point: ', X, ',',Y);
end;
{ Main }
Var
NumList, PointList : MyList;
Number, Coordinates: PMyListData;
I, J : Integer;
Begin
with NumList do begin { create list of numbers }
Init;
For I := 1 to 5 do
begin
Number := New(PMyNumber, Init(I));
AddToList(Number);
end;
Print;
end;
with PointList do begin { create list of points }
Init;
For I := 1 to 5 do
begin
J := I + 1;
Coordinates := New(PMyPoint, Init(I,J));
AddToList(Coordinates);
end;
Print;
end;
NumList.AddToList(Coordinates); { Coords can be added to Number list }
NumList.Print;
readln;
end.
[LISTING FOUR]
Parasol Implementation by Robert Jervis
include file;
/* any object that will appear in a list must inherit from this class */
MyListData: type { public:
Print: dynamic () = {
printf("No print method!\n");
}
};
MyList: public type inherit MyListData {
head: ref MyListElement;
tail: ref MyListElement;
MyListElement: type {
public:
data: ref MyListData;
next: ref MyListElement;
constructor: (initialData: ref MyListData) =
{ data = initialData; next = 0; }
};
public:
constructor: () = { head = tail = 0; }
AddToList: (data: ref MyListData) = {
newElement: ref MyListElement = new MyListElement[data];
if (head == 0)
head = tail = newElement;
else {
tail->next = newElement;
tail = newElement;
}
}
Print: dynamic () = {
element: ref MyListElement;
for (element = head; element != 0; element = element->next)
element->data Print();
}
};
MyNumber: type inherit MyListData {
value: int;
public:
constructor: (initialValue: int) = { value = initialValue; }
Print: dynamic () = {
printf("Number: %d\n", value);
}
};
MyPoint: type inherit MyListData {
x: int;
y: int;
public:
constructor: (initialX: int, initialY: int) = { x = initialX; y = initialY; }
Print: dynamic () = {
printf("Point: %d,%d\n", x, y);
}
};
main: entry () =
{
list1: ref MyList = new MyList[];
list2: ref MyList = new MyList[];
n1: ref MyNumber = new MyNumber[10];
n2: ref MyNumber = new MyNumber[20];
p1: ref MyPoint = new MyPoint[2,3];
p2: ref MyPoint = new MyPoint[4,5];
/* build the lists */
list1 AddToList(n1);
list1 AddToList(n2);
list1 AddToList(p1);
list2 AddToList(n2); /* an object can be in more than one list */
list2 AddToList(p1); /* at the same time */
list2 AddToList(p2);
list2 AddToList(list1); /* we can even put a list into another list */
/* print the lists */
printf("list1:\n");
list1 Print();
printf("list2:\n");
list2 Print();
}
[LISTING FIVE]
C+@ Implementation by Jim Fleming (Unir Corp.)
class MyListData {
method print
{
"No print method".print;
}
}
class MyListElement {
inherit MyListData;
MyListData data;
MyListElement next;
class method (_) new (initialData) {
_ = create
_.init(initialData);
}
method init (idata) {
data = idata;
next = nil;
}
method (_) data {
_ = data;
}
method(_) next {
_ = next;
}
method linkTo (listElement) {
next = listElement;
}
}
class MyList {
MyListElement head;
MyListElement tail;
class method (_) new {
_ = create;
_.init;
}
method init {
head = nil;
tail = nil;
}
method addToList (data) {
var newElement;
newElement = MyListElement.new(data);
if(head == nil) {
head = newElement;
tail = head;
}
else{
tail.linkTo(newElement);
tail = newELement;
}
}
method print {
var element;
for (element = head; element != nil; element = element.next) {
element.data.print;
}
}
}
class MyNumber {
Integer value;
class method (_) new (initialValue) {
_= create;
.init (initialValue)
}
method init (initialValue) {
value = initialValue;
}
method print {
("Number: " // value // "\n").print;
}
}
class MyPoint {
Integer x;
Integer y;
class method (_) new (initialX,initialY) {
_= create;
.init(initialX,initialY);
}
method init (initialX,initialY) {
x = initialX;
y = initialY;
}
method print {
("Point: "// x // "," // y // "\n").print
}
}
/* The following can be typed directly into command shell */
list1 = Mylist.new;
list2 = Mylist.new;
n1 = Mynumber.new(10);
n2 = Mynumber.new(20);
p1 = MyPoint.new(2,3);
p2 = MyPoint.new(4,5);
list1.addToList(n1);
list1.addToList(n2);
list1.addToList(p1);
list2.addToList(n2); /* an object can be in more than one list */
list2.addToList(p1);
list2.addToList(p2);
list2.addToList(list1); /* we can even put a list into another list */
/* print the lists */
"list1;\n".print;
list1.print;
"list2;\n".print;
list2.print;
[LISTING SIX]
Liana Implementation by Jack Krupansky (Base Technology)
class MyList : array
{
Print
{
for (int i = 0, int n = size; i < n; i++)
if ((any e = this [i]).isa ("MyList"))
e.Print();
else
cout << e.class_name+": "+e.text+"\n";
}
};
//-------------------------------------------
void main (void)
{
MyList list1 = new MyList;
MyList list2 = new MyList;
int n1 = 10;
int n2 = 20;
point p1 = new point (2,3);
point p2 = new point (4,5);
/* build the lists */
list1 << n1 << n2 << p1;
/* an obj can be in more than one lst at same time */
list2 << n2 << p1 << p2;
list2 << list1; /* we can even put a list into another list */
/* print the lists */
cout << "\nLIST1:\n"; list1.Print;
cout << "\nLIST2:\n"; list2.Print;
}
[LISTING SEVEN]
Minimal Smalltalk implementation by Ray Valdes (Dr. Dobb's Journal)
OrderedCollection subclass: #MyListClass
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!MyListClass class methods ! !
!MyListClass methods !
printOn: aStream
" Method to display list elements, recursing if necessary "
aStream cr; nextPutAll: ' ',(self class name),' '; cr.
self do: [:c | c printOn: aStream. aStream cr ].
^self.
!
test
" Program to test the linked-list class "
|
aList1 aList2 aNumber1 aNumber2 aPoint1 aPoint2 aMsg
|
aList1 := MyListClass new.
aList2 := MyListClass new.
aNumber1 := 10.
aNumber2 := 20.
aPoint1 := (2 @ 3).
aPoint2 := (4 @ 5).
" build the lists "
aList1 add: aNumber1; add: aNumber2; add: aPoint1.
" an object can be in more than one list at same time "
aList2 add: aNumber2; add: aPoint1; add: aPoint2.
" we can even put a list into another list "
aList2 add: aList1.
" print the lists "
aList1 printOn: Transcript.
aList2 printOn: Transcript.
! !
[LISTING EIGHT]
Complete Smalltalk/V implementation by Ray Valdes (Dr. Dobb's Journal)
"-------------------------------------------------------------"
Object subclass: #MyListClasses
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!MyListClasses class methods ! !
!MyListClasses methods ! !
"-------------------------------------------------------------"
MyListClasses subclass: #TestList
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!TestList class methods ! !
!TestList methods !
test
" Program to test the linked-list class "
|
aList1 aList2 aNumber1 aNumber2 aPoint1 aPoint2
|
aList1 := MyList new.
aList2 := MyList new.
aNumber1 := MyNumber new: 10.
aNumber2 := MyNumber new: 20.
aPoint1 := MyPoint new: (2 @ 3).
aPoint2 := MyPoint new: (4 @ 5).
" build the lists "
aList1 add: aNumber1; add: aNumber2; add: aPoint1.
" an object can be in more than one list at same time "
aList2 add: aNumber2; add: aPoint1; add: aPoint2.
" we can even put a list into another list "
aList2 add: aList1.
" print the lists "
aList1 print.
aList2 print! !
"------------------------------------------------------------------"
MyListClasses subclass: #MyListElement
instanceVariableNames: 'data next'
classVariableNames: ''
poolDictionaries: '' !
!MyListElement class methods !
new: someData
^super new initialize: someData! !
!MyListElement methods !
initialize: someData
data := someData.
^self!
next
^next!
next: anElement
next := anElement.
^self!
print
data print.
^self! !
"-------------------------------------------------------------"
MyListClasses subclass: #MyListData
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!MyListData class methods ! !
!MyListData methods !
print
Transcript cr; nextPutAll: 'Must override this method'; cr.
^self! !
"-------------------------------------------------------------"
MyListData subclass: #MyList
instanceVariableNames: 'head tail'
classVariableNames: ''
poolDictionaries: '' !
!MyList class methods ! !
!MyList methods !
add: someData
| anElement |
anElement := MyListElement new: someData.
head isNil
ifTrue: [ head := anElement. tail := anElement ]
ifFalse: [ tail next: anElement. tail := anElement].
^self!
print
| anElement |
anElement := head.
[anElement isNil]
whileFalse: [
anElement print.
anElement := anElement next .
Transcript cr.
].
^self! !
"-------------------------------------------------------------"
MyListData subclass: #MyNumber
instanceVariableNames: 'value'
classVariableNames: ''
poolDictionaries: '' !
!MyNumber class methods !
new: aValue
^super new initialize: aValue! !
!MyNumber methods !
initialize: aValue
value := aValue.
^self!
print
value printOn: Transcript.
^self! !
"-------------------------------------------------------------"
MyListData subclass: #MyPoint
instanceVariableNames: 'point'
classVariableNames: ''
poolDictionaries: '' !
!MyPoint class methods !
new: aPoint
^super new initialize: aPoint! !
!MyPoint methods !
initialize: aPoint
point := aPoint.
^self!
print
point printOn: Transcript.
^self! !
[LISTING NINE]
Eiffel Implementation by Robert Howard (Tower Technology)
class DRIVER
-- In Eiffel, the top level driver is an object, too.
inherit
BASIC_IO
creation
make
feature {ANY}
make is
-- run this test driver
local
list1, list2 : MY_LIST[PRINTABLE] ;
n1, n2 : MY_NUMBER ; -- a kind of PRINTABLE
p1, p2 : MY_POINT ; -- also a kinf of PRINTABLE
do
-- create the various objects
!!list1 ;
!!list2 ;
!!n1.set( 10 ) ;
!!n2.set( 20 ) ;
!!p1.set( 2, 3 ) ;
!!p2.set( 4, 5 ) ;
list1.add_to_list( n1 ) ;
list1.add_to_list( n2 ) ;
list1.add_to_list( p1 ) ;
list2.add_to_list( n2 ) ; -- objects can be in more than one list
list2.add_to_list( p1 ) ;
list2.add_to_list( p2 ) ;
list2.add_to_list( list1 ) ; -- list 1 is an element of list 2
put_string( "list1:%N" ) ;
list1.print_self ;
put_string( "list2:%N" ) ;
list2.print_self ;
end -- make
end -- DRIVER
deferred class PRINTABLE
-- insures that 'print_self' is implemented
inherit
BASIC_IO
feature {ANY}
print_self is
-- print yourself
deferred
end -- print_self
end -- PRINTABLE
class MY_NUMBER
-- holds and can print an integer
inherit
PRINTABLE
creation
set
feature {ANY}
value : INTEGER ;
set( new_value : INTEGER ) is
-- set this number
do
value := new_value ;
end ; -- make
print_self is
-- print the value
do
put_string( "Number: " ) ;
put_int( value ) ;
put_newline ;
end ; -- print_self
end -- MY_NUMBER
class MY_POINT
-- holds and can print an x,y pair
inherit
PRINTABLE
creation
set
feature {ANY}
x, y : INTEGER ;
set( new_x : INTEGER; new_y : INTEGER ) is
-- set this point
do
x := new_x ;
y := new_y
end ; -- set
print_self is
-- print the value
do
put_string( "Point: " ) ;
put_int( x ) ;
put_char( ',' ) ;
put_int( y ) ;
put_newline ;
end ; -- print_self
end -- MY_POINT
class ELEMENT[T]
-- holds an object reference and a
-- single link to another ELEMENT[T]
creation
set_data
feature {LIST}
data : T ;
next : ELEMENT[T] ;
set_data( new_data : T ) is
-- set data to the new_data
do
data := new_data
end ; -- set_data
set_next( new_next : ELEMENT[T] ) is
-- set next to the element
do
next := new_next
end ; -- set_next
end -- class ELEMENT
class LIST[T]
-- a generic linked list class
feature {ANY}
add_to_list( data : T ) is
-- add to the end of the list
local
new_element : ELEMENT[T] ;
do
!!new_element.set_data( data ) ;
if head = void
then
head := new_element ;
else
tail.set_next( new_element ) ;
end
tail := new_element ;
end ; -- add_to_list
feature {NONE}
head, tail : ELEMENT[T] ;
invariant
tail_next_is_void: tail.next = void ;
tail_void_when_head_void: head = void implies tail = void
end -- LIST
class MY_LIST[T->PRINTABLE]
-- A printable list which holds printable data
inherit
LIST[T]
PRINTABLE
feature {ANY}
print_self is
-- print the list elements
local
el : ELEMENT[T] ;
do
from
el := head
until
el = void
loop
el.data.print_self
el := el.next ;
end ;
end ; -- print_self
end -- MY_LIST
[LISTING TEN]
Sather Implementation by Stephen Omhundro (ICSI)
-------------------------------------------------------------------
abstract class $MY_LIST_DATA is
-- Data that will appear in a list must inherit this class.
print is
-- Print the data on OUT. Should be redefined in descendants.
#OUT + "No print routine defined!\n" end;
end;
-------------------------------------------------------------------
class MY_LIST_ELEMENT is
-- An element of a MY_LIST.
attr data:$MY_LIST_DATA;
attr next:MY_LIST_ELEMENT;
end;
-------------------------------------------------------------------
class MY_LIST is
-- A double ended linked list.
inherit $MY_LIST_DATA;
private head, tail:MY_LIST_ELEMENT;
add_to_list($MY_LIST_DATA) is
-- Append arg to the end of self.
new_elt::=#MY_LIST_ELEMENT(data:=arg);
if head=void then head:=new_elt
else tail.next:=new_elt end;
tail:=new_elt end;
print is
-- Print the data held in the list on OUT.
elt::=head;
loop while!(elt/=void); elt.data.print;
elt:=elt.next end end;
end;
-------------------------------------------------------------------
class MY_NUMBER is
-- An integer value that can be held in a MY_LIST.
inherit $MY_LIST_DATA;
attr value:INT;
print is
-- Print the integer value on OUT.
#OUT + "Number: " + value + "\n" end;
end;
-------------------------------------------------------------------
class MY_POINT is
-- A two-dimensional point that can be held in a MY_LIST.
inherit $MY_LIST_DATA;
attr x,y:INT;
print is
-- Print the point coordinates on OUT.
#OUT + "Point: " + x + "," + y + "\n" end;
end;
-------------------------------------------------------------------
class MY_LIST_TEST is
-- Test of MY_LIST.
main is
-- Add some numbers and points to lists and print them out.
list1::=#MY_LIST; list2::=#MY_LIST;
n1::=#MY_NUMBER(10); n2::=#MY_NUMBER(20);
p1::=#MY_POINT(2,3); p2::=#MY_POINT(4,5);
-- Build the lists:
list1.add_to_list(n1); list1.add_to_list(n2);
list1.add_to_list(p1);
list2.add_to_list(n2); -- An object can be in more than one list.
list2.add_to_list(p1); list2.add_to_list(p2);
list2.add_to_list(list1); -- Put a list in another list.
-- Print the lists
#OUT + "list1:\n";
list1.print;
#OUT + "list2:\n";
list2.print end;
end;
[LISTING ELEVEN]
Beta Implementation by Steve Mann (MADA)
--- program:descriptor---
(#
MyListData: (# Print:< (# do INNER #) #);
MyListElement: (# data: ^MyListData; next: ^MyListElement; #);
MyList: MyListData (#
head, tail: ^MyListElement;
AddToList: (#
newItem: ^MyListData
enter newItem[]
do (if head[] = NONE // TRUE then
&MyListElement[] -> head[] -> tail[];
newItem[] -> head.data[];
else
&MyListElement[]-> tail.next[] -> tail[];
newItem[] -> tail.data[];
if);
#);
Print::< (#
element: ^MyListElement
do head[] -> element[];
loop (# while::< (# do element[] <> NONE -> value #);
do element.data.print; element.next[] -> element[];
#); #); #);
MyNumber: MyListData (#
value: @integer;
Print::< (# do 'Number: ' -> PutText; value -> PutInt; NewLine; #);
enter value
#);
MyPoint: MyListData (#
x, y: @integer;
Print::< (# do 'Point: ' -> PutText; x -> PutInt;
', ' -> PutText; y -> PutInt;NewLine;
#);
enter (x, y)
#);
(********************** MAIN **************************)
list1, list2: @MyList;
n1, n2: @MyNumber; p1, p2: @MyPoint;
do
10 -> n1; 20 -> n2;
(2, 3) -> p1; (4, 5) -> p2;
n1[] -> list1.AddToList;n2[] -> list1.AddToList;
p1[] -> list1.AddToList;
n2[] -> list2.AddToList;p1[] -> list2.AddToList;
p2[] -> list2.AddToList;list1[] -> list2.AddToList;
'list1: ' -> PutLine; list1.Print;
'list2: ' -> PutLine; list2.Print;
#)
[LISTING TWELVE]
Drool Implementation by David Betz (Dr. Dobb's Journal)
(defobject MyListElement ()
(property next nil
data nil))
(defobject MyList ()
(property head nil
tail nil))
(defmethod (MyList 'AddToList data)
(let ((newElement (clone MyListElement 'data data))
(tail (getp self 'tail)))
(if tail
(setp! tail 'next newElement)
(setp! self 'head newElement))
(setp! self 'tail newElement)))
(defmethod (MyList 'Print)
(let ((element (getp self 'head)))
(while element
((getp element 'data) 'Print)
(set! element (getp element 'next)))))
(defobject MyNumber ()
(property value 0))
(defmethod (MyNumber 'Print)
(print "Number: " (getp self 'value) "\n"))
(defobject MyPoint ()
(property x 0
y 0))
(defmethod (MyPoint 'Print)
(print "Point: " (getp self 'x) "," (getp self 'y) "\n"))
(define (main)
(let ((list1 (clone MyList))
(list2 (clone MyList))
(n1 (clone MyNumber 'value 10))
(n2 (clone MyNumber 'value 20))
(p1 (clone MyPoint 'x 2 'y 3))
(p2 (clone MyPoint 'x 4 'y 5)))
(list1 'AddToList n1)
(list1 'AddToList n2)
(list1 'AddToList p1)
(list2 'AddToList n2)
(list2 'AddToList p1)
(list2 'AddToList p2)
(list2 'AddToList list1)
(print "list1\n")
(list1 'Print)
(print "list2\n")
(list2 'Print)))
[LISTING THIRTEEN]
Ada Implementation by Mike Ruf (Rational)
-- Ada83 does not support run-time polymorphism, so only supports homogeneous
-- lists. Ada9X will run-time polymorphism. There are ways to simulate run-time
-- polymorphism in Ada83, which is discussed in: Seidewitz, Ed,
-- "Object-Oriented Programming Through Type Extension in Ada 9X," Ada
-- Letters, Volume 11, Number 2, Mar/Apr 1991, pages 86-97. Hirasuna, Michael,
-- "Using Inheritance and Polymorphism with Ada in Government Sponsored
-- Contracts", Ada Letters, Volume 12, Number 2, Mar/Apr, 1992, pp. 43-56.
-- Mike Ruf, Rational Systems
-- This package implements a singly-linked list abstraction.
--
generic
type Element is private;
with procedure Print (This : Element);
package Printable_List_Generic is
type List is private;
function New_List return List;
-- Returns an empty list.
procedure Append (To_List : in out List;
This_Element : in Element);
-- Propagates the Storage_Error exception if it occurs.
procedure Print (This : in List);
-- For each element in the list, calls the Print procedure,
-- which is supplied as a generic formal parameter.
private
type Node;
type Pointer is access Node;
type Node is
record
Contents : Element;
Next : Pointer := null;
end record;
type List is
record
First : Pointer := null;
Last : Pointer := null;
end record;
end Printable_List_Generic;
package body Printable_List_Generic is
function New_List return List is
begin
return (List'(First => null, Last => null));
end New_List;
procedure Append (To_List : in out List;
This_Element : in Element) is
New_Node : Pointer := new Node'(Contents => This_Element, Next => null);
-- The "next" component of the last node is always "null"
begin
if To_List.First = null then
To_List.First := New_Node;
To_List.Last := New_Node;
else
To_List.Last.Next := New_Node;
To_List.Last := New_Node;
end if;
end Append;
procedure Print (This : in List) is
Current : Pointer := This.First;
begin
while (not (Current = null)) loop
Print (Current.Contents);
Current := Current.Next;
end loop;
end Print;
end Printable_List_Generic;
package Geometry is
type Number is new Integer;
procedure Print (This : Number);
type Point is
record
X : Number := 0;
Y : Number := 0;
end record;
procedure Print (This : Point);
end Geometry;
package body Geometry is
procedure Print (This : Number) is
begin
Text_Io.Put_Line ("Number:" & Number'Image (This));
end Print;
procedure Print (This : Point) is
begin
Text_Io.Put_Line ("Point: " & Number'Image (This.X) &
"," & Number'Image (This.Y));
end Print;
end Geometry;
procedure List_Example;
with Geometry;
with Printable_List_Generic;
procedure List_Example is
package Numbers is new Printable_List_Generic (Element => Geometry.Number,
Print => Geometry.Print);
package Points is new Printable_List_Generic (Element => Geometry.Point,
Print => Geometry.Print);
Number_List : Numbers.List := Numbers.New_List;
Point_List : Points.List := Points.New_List;
N1 : Geometry.Number := 10;
N2 : Geometry.Number := 20;
P1 : Geometry.Point := (2, 3);
P2 : Geometry.Point := (4, 5);
begin
-- Build the lists
Numbers.Append (To_List => Number_List, This_Element => N1);
Numbers.Append (To_List => Number_List, This_Element => N2);
--
Points.Append (To_List => Point_List, This_Element => P1);
Points.Append (To_List => Point_List, This_Element => P2);
-- Print the lists
Numbers.Print (Number_List);
Points.Print (Point_List);
end List_Example;
------------------------------- OUTPUT -------------------------------
Number: 10
Number: 20
Point: 2, 3
Point: 4, 5